package sicnu.cs.aps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sicnu.cs.aps.common.Constants;
import sicnu.cs.aps.common.enums.ActivityTeamMemberInviteEnum;
import sicnu.cs.aps.common.util.RequestUtil;
import sicnu.cs.aps.common.util.ValidateUtils;
import sicnu.cs.aps.domain.entity.*;
import sicnu.cs.aps.mapper.ActivitySignMapper;
import sicnu.cs.aps.service.*;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

/**
 * @author chengke
 * @version 1.0
 * @className ActivitySignServiceImpl
 * @description 创建活动信息实现类
 * @date 2022/5/27 11:34
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ActivitySignServiceImpl extends ServiceImpl<ActivitySignMapper, ActivityTeam> implements IActivitySignService {

    private final ActivitySignMapper activitySignMapper;

    private final IUserService userService;
    private final ITeacherInfoService teacherInfoService;
    private final IStudentInfoService studentInfoService;
    private final ISendMailService sendMailService;
    private final IActivityRestrictionService restrictionService;
    private final ITeamMemberService memberService;
    private final ITeamMemberInviteService inviteService;

    @Override
    public List<Long> selectUserIdByActivityId(Long ActivityId) {
        return activitySignMapper.selectUserIdByActivityId(ActivityId);
    }

    @Override
    public List<Long> selectTeamIdByActivityId(Long activityId) {
        return activitySignMapper.selectTeamIdByActivityId(activityId);
    }

    @Override
    public Long selectTeamIdByUserIdAndActivityId(Long userId, Long activityId) {
        return activitySignMapper.selectTeamIdByUserIdAndActivityId(userId, activityId);
    }

    @Override
    public Long selectUserIdByTeamId(Long teamId) {
        return activitySignMapper.selectUserIdByTeamId(teamId);
    }

    @Override
    @Async
    @Transactional(rollbackFor = RuntimeException.class)
    public void inviteTeacherWhenSignup(Long currentUserId, Long teacherId, ActivityTeam currentTeam, Activity currentActivity) {
        final long start = System.currentTimeMillis();
//        log.info("开始邀请老师。{}", start);
        final TeacherInfo teacherToInvite = teacherInfoService.getById(teacherId);
        if (teacherToInvite == null) {
            log.info("{}邀请的指导老师：{}不存在。", currentTeam.getId(), teacherId);
            return;
        }
        final StudentInfo currentStu = studentInfoService.getById(currentUserId);
        if (!teacherToInvite.getCollegeId().equals(currentStu.getCollegeId())) {
            log.info("{}邀请的指导老师：{}与队长不在同一所学院", currentTeam.getId(), teacherId);
            return;
        }
        // 生成Token
        final String inviteToken = ValidateUtils.createValidateCode(16);
        final String context = currentStu.getName() + "邀请您作为指导老师参加【" + currentActivity.getTitle() + "】活动的【" + currentTeam.getName() + "】队伍，如果您同意邀请，请在24小时内点击下方链接："
                + Constants.APS_BASE_URL + "invite?token=" + inviteToken;
        sendMailService.sendInformEmail(userService.findUser(teacherId).getEmail(), context);
//        log.info("邀请老师完成，{}", System.currentTimeMillis() - start);

        var now = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, 1);
        Date nextDay = calendar.getTime();
        var teamMemberInviteToSave = ActivityTeamMemberInvite.builder()
                .userId(currentUserId)
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_TEACHER.getIndex())
                .activityId(currentTeam.getId())
                .token(inviteToken)
                .tokenValidTime(nextDay)
                .createTime(now)
                .build();
        inviteService.save(teamMemberInviteToSave);
    }

    @Override
    @Async
    @Transactional(rollbackFor = RuntimeException.class)
    public void inviteStudentsWhenSignup(Long currentUserId, List<Long> studentIds, ActivityTeam currentTeam, Activity currentActivity) {
        final ActivityRestriction restriction = restrictionService.getById(currentActivity.getId());
        if (!restriction.getTeamSize().equals(-1)) {
            final QueryWrapper<TeamMember> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("team_id", currentTeam.getId());
            if (memberService.count(queryWrapper) >= restriction.getTeamSize()) {
                log.info("{}的队伍人数已达上限{}人", currentTeam.getId(), restriction.getTeamSize());
                return;
            }
        }
        // 生成Token
        final StudentInfo currentStu = studentInfoService.getById(currentUserId);
        final String inviteToken = ValidateUtils.createValidateCode(16);
        final String context = currentStu.getName() + "邀请您作为指导老师参加【" + currentActivity.getTitle() + "】活动的【" + currentTeam.getName() + "】队伍，如果您同意邀请，请在24小时内点击下方链接："
                + Constants.APS_BASE_URL + "invite?token=" + inviteToken;
        userService.listById(studentIds).stream().map(User::getEmail).forEach(email -> {
            sendMailService.sendInformEmail(email, context);
        });

        var now = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, 1);
        Date nextDay = calendar.getTime();
        var teamMemberInviteToSave = ActivityTeamMemberInvite.builder()
                .userId(currentUserId)
                .type(ActivityTeamMemberInviteEnum.INVITE_AS_MEMBER.getIndex())
                .activityId(currentTeam.getId())
                .token(inviteToken)
                .tokenValidTime(nextDay)
                .createTime(now)
                .build();
        inviteService.save(teamMemberInviteToSave);


    }
}